package com.ws.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ws.dao.CzsbLogMapper;
import com.ws.dao.SssfmDcWsUnifySmMapper;
import com.ws.dao.YthManagerMapper;
import com.ws.entity.CzsbLog;
import com.ws.entity.SssfmDcWsUnifySm;
import com.ws.entity.YthManager;
import com.ws.service.DemoService;
import com.ws.service.YthService;
import com.ws.utils.base.YthResCodeEnum;
import com.ws.utils.safeUtil.SM2Utils;
import com.ws.utils.safeUtil.SafeUtil;
import com.ws.utils.safeUtil.Util;
import com.ws.utils.sm.SM4Utils;
import com.ws.utils.xmlUtil.DcRegexUtils;
import com.ws.utils.xmlUtil.MapToXml;
import com.ws.utils.xmlUtil.SearchMapByKey;
import com.ws.utils.xmlUtil.XmlToMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.jws.WebParam;
import javax.jws.WebService;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName DemoServiceImpl
 * @Description TODO
 * @Author zhengchenggong
 * @Date 2020/7/14 1:58 下午
 * @Version 1.0
 **/

@Transactional
@WebService(serviceName = "YthService", // 与接口中指定的name一致
        targetNamespace = "http://impl.service.server.shebao.webservice.ifmis.fasp.mof.gov/", // 与接口中的命名空间一致,一般是接口的包名倒
        endpointInterface = "com.ws.service.YthService"// 接口地址
)
@Slf4j
@Service
public class YthServiceImpl implements YthService {

    @Autowired
    SssfmDcWsUnifySmMapper sssfmDcWsUnifySmMapper;

    @Autowired
    CzsbLogMapper czsbLogMapper;

    @Autowired
    YthManagerMapper ythManagerMapper;

    public static SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
    public static SimpleDateFormat formatterYear = new SimpleDateFormat("yyyy");

    ThreadLocal<String> threadLocal = new ThreadLocal<>();

    @Override
    public String getSM4SignInfo(@WebParam(name = "sidXml", targetNamespace = "http://impl.service.server.shebao.webservice.ifmis.fasp.mof.gov/") String sidXml) {
        log.error("收到报文：" + sidXml);
        //对方公钥(社保公钥)
        String opsPblKey = "04EDA367BF0E95DE06BA7B8A366019813830C1C4EF7B18EFD01E478D41FA2F0283726C61C01513CE2D3438209FB17993D39FC2F6F84C4A4DE58F8564699306D718";
        //本方私钥（一体化私钥）
        String selfPrtKey = "37871BFB758814FB5F633F9B2CDA7F8B53C1C9409FBDA986CDEE05CE96144001";
        String xml = "";
        String sid = "";
        String plainText = "";//收到的明文报文
        try {
            String decode = SafeUtil.decode(sidXml, "utf-8");
            //sm2解密
            plainText = new String(SM2Utils.decrypt(Util.hexToByte(selfPrtKey), Util.hexToByte(decode)));//sm2解密
            //解析报文
            sid = DcRegexUtils.getHtml("SID", plainText); //获取发送来的SID
            System.out.println("sid:" + sid);
            //生成sm4密钥
            String sm4Key = SM4Utils.generateKey();
            System.err.println("----------------------------------sm4Key:" + sm4Key);
            log.info("得到sm4Key：" + sm4Key);
            SssfmDcWsUnifySm sssfmDcWsUnifySm = new SssfmDcWsUnifySm();
            sssfmDcWsUnifySm.setAppid("appId1205");
            sssfmDcWsUnifySm.setSid(sid);
            sssfmDcWsUnifySm.setSmCode(sm4Key);
            sssfmDcWsUnifySmMapper.insert(sssfmDcWsUnifySm);
            log.info("完成sm4Key入库");
//            SssfmDcWsUnifySm sssfmDcWsUnifySm1 = sssfmDcWsUnifySmMapper.selectById(sid);
//            System.out.println(sssfmDcWsUnifySm1);
            xml = this.packSm4Xml(sidXml, sm4Key, opsPblKey);
        } catch (Exception e) {
            e.printStackTrace();
            xml = "公钥私钥不匹配";
        }
        System.out.println("xml返回=====" + xml);
        return xml;
    }

    @Override
    public String pushPayMainInfo(@WebParam(name = "vous", targetNamespace = "http://impl.service.server.shebao.webservice.ifmis.fasp.mof.gov/") String vous, @WebParam(name = "sid", targetNamespace = "http://impl.service.server.shebao.webservice.ifmis.fasp.mof.gov/") String sid) {
        String res = null;
        Map<String, Object> req = null;
        try {
            List<YthManager> ythManagers = ythManagerMapper.selectList(new QueryWrapper<>());
            if (!CollectionUtils.isEmpty(ythManagers)) {
                String resCode = ythManagers.get(0).getResCode();
                if (!"0000".equals(resCode)) {
                    res = this.packErrResXml(req, sid, resCode);
                } else {
                    req = (Map<String, Object>) this.msgToObj(vous, sid, "map");
                    System.out.println("收到的报文：" + req);
                    res = this.packResXml(req, sid);
                }

            } else {
                throw new RuntimeException("未查询到管理表yth_Manager");
            }
        } catch (Exception e) {
            e.printStackTrace();
            res = this.packErrResXml(req, sid, "0001");
        } finally {
            if (StringUtils.isBlank(sid)) {
                sid = UUID.randomUUID().toString().replace("-", "");
            }
            CzsbLog czsbLog = new CzsbLog();
            czsbLog.setId(sid);
            czsbLog.setReceivemsg(JSON.toJSONString(req));
            czsbLog.setSendmsg(threadLocal.get());
            czsbLogMapper.insert(czsbLog);
            return res;
        }
    }

    private String packSm4Xml(String vous, String sm4Key, String opsPblKey) throws Exception {
        String xml = "";
        //组织报文返回给客户端
        String ver = DcRegexUtils.getHtml("VER", vous);
        Map<String, Object> sidMap = new LinkedHashMap<String, Object>();
        sidMap.put("SM4", sm4Key);
        Map<String, Object> dataBodyMap = new LinkedHashMap<String, Object>();
        dataBodyMap.put("DATA", sidMap);
        Map<String, Object> bodyMap = new LinkedHashMap<String, Object>();
        bodyMap.put("DATACOUNT", "1");
        bodyMap.put("DATABODY", dataBodyMap);

        /**
         * 封装head
         */
        long currentTimeMillis = System.currentTimeMillis();
        String workDate = formatter.format(currentTimeMillis);
        String year = formatterYear.format(currentTimeMillis);
        Map<String, Object> headMap = new LinkedHashMap<String, Object>();
        headMap.put("VER", ver);
        headMap.put("DATATYPE", "xml");
        headMap.put("SRC", "YTH");
        headMap.put("DES", "SHEBAO");
        headMap.put("MSGNO", "getSM4SignInfo");
        headMap.put("MSGREF", "ooooooopppppppppp");
        headMap.put("WORKDATE", workDate);
        headMap.put("STYEAR", year);
        headMap.put("ADMINDIV", "230000");
        headMap.put("RESERVE1", "");
        headMap.put("RESERVE2", "");
        headMap.put("RESERVE3", "");
        Map<String, Object> bizMap = new LinkedHashMap<String, Object>();
        bizMap.put("HEAD", headMap);
        bizMap.put("MSG", bodyMap);//data节点是一个map

        Map<String, Object> rootMap = new LinkedHashMap<String, Object>();
        rootMap.put("FIRD", bizMap);
        xml = MapToXml.mapToXML(rootMap, "GBK");
        log.info("返回给客户端报文：" + xml);
        String cipherText = SM2Utils.encrypt(Util.hexToByte(opsPblKey), xml.getBytes());
        xml = SafeUtil.encode(cipherText, "utf-8");
        System.out.println("加密后报文：" + xml);
        return xml;
    }

    //成功报文
    private String packResXml(Map req, String sid) {
        Map<String, Object> msgMap = new LinkedHashMap<String, Object>(); //报文信息
        Map<String, Object> headMap = new LinkedHashMap<String, Object>(); //报文头
        Map<String, Object> rootMap = new LinkedHashMap<String, Object>();//总报文
        Map<String, Object> map = new LinkedHashMap<String, Object>();//总报文

        long currentTimeMillis = System.currentTimeMillis();
        String workDate = formatter.format(currentTimeMillis);
        String year = formatterYear.format(currentTimeMillis);
        rootMap.put("HEAD", headMap);
        rootMap.put("MSG", msgMap);
        map.put("FIRD", rootMap);
        headMap.put("VER", "1.0");
        headMap.put("DATATYPE", "xml");
        headMap.put("SRC", SearchMapByKey.get(req, "DES") == null ? "YTH" : SearchMapByKey.get(req, "DES").toString());
        headMap.put("DES", SearchMapByKey.get(req, "SRC") == null ? "CZSB" : SearchMapByKey.get(req, "SRC").toString());
        headMap.put("MSGNO", "getPayVou");
        headMap.put("SESSIONID", SearchMapByKey.get(req, "SESSIONID") == null ? "" : SearchMapByKey.get(req, "SESSIONID").toString());
        headMap.put("MSGREF", SearchMapByKey.get(req, "MSGREF") == null ? "" : SearchMapByKey.get(req, "MSGREF").toString());
        headMap.put("WORKDATE", workDate);
        headMap.put("STYEAR", year);
        headMap.put("ADMINDIV", SearchMapByKey.get(req, "ADMINDIV") == null ? "" : SearchMapByKey.get(req, "ADMINDIV").toString());
        headMap.put("RESERVE1", "");
        headMap.put("RESERVE2", "");
        headMap.put("RESERVE3", "");
        msgMap.put("DATACOUNT", "1");
        Map data = new HashMap();
        data.put("CODE", "0000");
        msgMap.put("DATABODY", data);
        System.out.println(map);
        return this.objToMsg(null, map, sid);
    }

    //失败报文
    private String packErrResXml(Map req, String sid, String resCode) {
        Map<String, Object> msgMap = new LinkedHashMap<String, Object>(); //报文信息
        Map<String, Object> headMap = new LinkedHashMap<String, Object>(); //报文头
        Map<String, Object> rootMap = new LinkedHashMap<String, Object>();//总报文
        Map<String, Object> map = new LinkedHashMap<String, Object>();//总报文

        long currentTimeMillis = System.currentTimeMillis();
        String workDate = formatter.format(currentTimeMillis);
        String year = formatterYear.format(currentTimeMillis);
        rootMap.put("HEAD", headMap);
        rootMap.put("MSG", msgMap);
        map.put("FIRD", rootMap);
        headMap.put("VER", "1.0");
        headMap.put("DATATYPE", "xml");
        headMap.put("SRC", "YTH");
        headMap.put("DES", "CZSB");
        headMap.put("MSGNO", "getPayVou");
        headMap.put("WORKDATE", workDate);
        headMap.put("STYEAR", year);
        headMap.put("RESERVE1", "");
        headMap.put("RESERVE2", "");
        headMap.put("RESERVE3", "");
        msgMap.put("DATACOUNT", "1");
        Map data1 = new HashMap();
        data1.put("CODE", resCode);//失败
        data1.put("MSG", YthResCodeEnum.Error.getMsg(resCode)==null?"未知的错误":YthResCodeEnum.Error.getMsg(resCode));//失败
        Map data = new HashMap();
        data.put("DATA",data1);
        msgMap.put("DATABODY", data);
        System.out.println(map);
        return this.objToMsg(null, map, sid);
    }


    private Object msgToObj(String msg, String sid, String type) {
        Object result = new Object();
        try {
            String msgSm4 = SafeUtil.decode(msg, "utf-8");
            SssfmDcWsUnifySm sssfmDcWsUnifySm = sssfmDcWsUnifySmMapper.selectById(sid);
            if (sssfmDcWsUnifySm != null) {
                String sm4Key = sssfmDcWsUnifySm.getSmCode() == null ? "" : sssfmDcWsUnifySm.getSmCode();
                String xmlMsg = SM4Utils.decryptData_ECB(msgSm4, sm4Key);
                if (type.equals("map"))
                    result = XmlToMap.xmlToMap(xmlMsg);
                else
                    result = xmlMsg;
            } else {
                throw new RuntimeException("sssfm_dc_ws_unify_sm表获取的sm编码有误");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }


    private String objToMsg(String xmlMsg, Map map, String sid) {
        String msgCode = "GBK";
        String msgBase64 = null;
        try {
            String smJobId = null, oppoJobId = null;

            SssfmDcWsUnifySm sssfmDcWsUnifySm = sssfmDcWsUnifySmMapper.selectById(sid);
            if (sssfmDcWsUnifySm != null) {
                String sm4Key = sssfmDcWsUnifySm.getSmCode() == null ? "" : sssfmDcWsUnifySm.getSmCode();
                if (xmlMsg == null)
                    xmlMsg = MapToXml.mapToXML(map, msgCode);
                threadLocal.set(xmlMsg);
                log.error("aaa加密前报文-->" + xmlMsg);
                log.error("sm4Key->" + sm4Key);
                String msgSm4 = SM4Utils.encryptData_ECB(xmlMsg, sm4Key);
                log.error("aaa加密后报文-->" + msgSm4);
                msgBase64 = SafeUtil.encode(msgSm4, "utf-8");
                log.error("aaa编码后报文-->" + msgBase64);
                // sm秘钥使用完成后，删除
                sssfmDcWsUnifySmMapper.deleteById(sid);

            } else {
                throw new RuntimeException("sssfm_dc_ws_unify_sm表获取的sm编码有误");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return msgBase64;
    }


    public static void main(String[] args) {
        YthServiceImpl ythService = new
                YthServiceImpl();
        ythService.getSM4SignInfo("MDRBRDE2NjYyMUI5NzI5Q0VCQjdDODg3RkQ0NzFCOTk1NDlFMTU1RkE4RUZDQTM4MkVERUY5MjcwNUE2QUJERjhBMDAwMDBGOTBGOUY3MUFFRjA5OEQzMjE5MkFEMTdDQTc5RDQwNDIyRTg0NjZCNUQyQ0RCRjVCMUNGRDNGMTIwOEE2MTY5REYzMjkwQkNFNjRGNUI0NENDRDNGMERCNUQ0OTQyNTI2RDAwNUVBOUYxQzVCMDk3MkUwNkQ5Q0E5QjY2NzVDMkY0QjgyMThGMjg1NzFGMTFCMDNDOTExNUI2MDBCQkE1MzMzQTY4QzgzMUQzM0EwQTBGN0Y2RDg2QTY1NjREMkE4QTUxMTZDQTREQjBEMTdCRDExMzIyQ0UzM0IyQjU4MjFGMTc0Qzc4NDczRDNDRjEzOTdBNUJGRjk5OTQ2MzU4MUI2NzI4ODk3MTIyQzI5RDYxNjNFOTFBNEEzMTVGQkQwRDg1OTU1OTg0N0E1REJCMTJCMzMyNTUwRjAyOTUwOTI1MTMzNUU3ODI0RTZDRUMxQTMwOTIzMzFCQzZBODE3RDBFQzBGNjk4QThCNDUwNzcxN0ZGRUMyMzczRTI2MDY4NzhERjNGMzQyRDEwMDFFRTRENzVFNTIzN0FDOUVBRDY2NzQzMDA5MDI0MjM1ODcwQUE3MDAzODBERjZGRENDRUQ2ODUwNDgzNTYxRjhBM0MyRTIwMTUyRTc5QkE2MjE1RkNCOTRGNTQ5QjZFODE4QkI4NkI4M0ZBNDMyNjMxMEQxREZGMjI3REVDNTM3QTRBMDA1MjJGMTVDMkM3Q0IzMEMwM0EyNjI3MUMzMTA0Q0FBNUZEMTEwRkZFQjM2QTI0NDFGN0E5QTlCRjE2OTlFMTcxMTE0QjM1QkI0NDYwQTg2MTMwNTlCQzcwNEU2Q0I0MDhCMDUwNjNDNDREMEY4MTQ4OTMxNDY0NjkwMTE3Qjc0NjMxMDhGRThBRjdGQjk1MkY0MDcxRDA0N0MyQjREM0YzNjA3NEI5RjE3QTY5RjZBRTFBNjlCRjM4NTc0NDk4RjVERUVGNDk1MTg4M0FBQzk3RUY5MTUzNTc1QzlGQzc4OTVEODYwQjMxQjNDM0JGNUY4MDBFQzZGNzU1ODNEQTY3NzJDNUM1QkZEOERFNzU3NkU0ODg2MjNEQkIzQjM0QjNCODBEMkEwNjE0MEQwQjQ3NDU5QTQ4ODZGREYxOUU5MzQ3QUE2RTZCMzMzNUU4ODM2ODMxNDNENDFFNUUwMkNBMjFCMjY0MjUwQzJEODM4RUZDOTZBMTEwRTM3MkE1MDI5QzU0ODBGMkJGRUJCODQ4MjU1MDM2ODQ3OTUzMTNFOTEyODhDMzc0QzVDNDRBOERBOTBDMUUwODc0QUEwMDFCRUY2RkExMERBODU2QUZENDZEODdDODFCRTNDQkI4QkEyRjI0");
    }

}
